package com.caipos.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.caipos.actor.common.data.BaseData;
import com.caipos.actor.common.data.EntityType;
import com.caipos.actor.common.data.relation.Relation;
import com.caipos.actor.common.data.relation.RelationTypeGroup;
import com.caipos.actor.common.data.rule.RuleChain;
import com.caipos.actor.common.data.rule.RuleNode;
import com.caipos.mapper.RelationMapper;
import com.caipos.mapper.RuleChainMapper;
import com.caipos.mapper.RuleNodeMapper;
import com.caipos.service.RelationService;
import com.caipos.service.RuleChainService;
import com.caipos.util.Validator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class RuleChainServiceImpl extends ServiceImpl<RuleChainMapper, RuleChain> implements RuleChainService {
    @Lazy
    @Autowired
    protected RelationService relationService;

    @Autowired
    private RuleNodeMapper ruleNodeMapper;

    @Autowired
    private RuleChainMapper ruleChainMapper;

    @Override
    public RuleChain getRuleChainById(String id) {
        return getById(id);
    }

    @Override
    public List<RuleChain> getAllRuleChains() {
        return list();
    }

    @Override
    public IPage<RuleChain> getRuleChainsByPage(Page<RuleChain> page) {
        return baseMapper.selectPage(page, null);
    }

    @Override
    public boolean saveRuleChain(RuleChain ruleChain) {
        return save(ruleChain);
    }

    @Override
    public boolean updateRuleChain(RuleChain ruleChain) {
        return updateById(ruleChain);
    }

    @Override
    public boolean deleteRuleChainById(String id) {
        return removeById(id);
    }

    @Override
    public List<RuleChain> getRuleChainsByTenantId(String tenantId) {
        return baseMapper.selectByTenantId(tenantId);
    }

    @Override
    public List<Relation> getRuleNodeRelations(RuleNode ruleNode) {
        Validator.validateId(ruleNode.getRuleChainId(), "Incorrect rule node id for search request.");
        List<Relation> relations = relationService.findRelationsByRelation(Relation.builder()
                .fromId(ruleNode.getId())
                .relationTypeGroup(EntityType.RULE_NODE)
                .build());
        List<Relation> validRelations = new ArrayList<>();
        for (Relation relation : relations) {
            boolean valid = true;
            EntityType toType = relation.getToType();
            if (toType == EntityType.RULE_NODE || toType == EntityType.RULE_CHAIN) {
                boolean entityExists;
                if (relation.getToType() == EntityType.RULE_NODE) {
                    entityExists = ruleNodeMapper.selectById(relation.getToId())!=null;
                } else {
                    entityExists = ruleChainMapper.selectById(relation.getToId())!=null;
                }
                if (!entityExists) {//关系查不到
                    relationService.deleteByRelation(relation);
                    valid = false;
                }
            }
            if (valid) {
                validRelations.add(relation);
            }
        }
        return validRelations;
    }

    @Override
    public List<RuleNode> getRuleChainNodesByRuleChainId(String ruleChainId) {
        Validator.validateId(ruleChainId, "Incorrect rule chain id for search request.");
        List<Relation> relations = relationService.findRelationsByRelation(Relation.builder().fromId(ruleChainId).build());
        List<RuleNode> ruleNodes = new ArrayList<>();
        for (Relation relation : relations) {
            RuleNode ruleNode = ruleNodeMapper.selectById(relation.getToId());
            if (ruleNode != null) {
                ruleNodes.add(ruleNode);
            } else {
                relationService.deleteByRelation(relation);
            }
        }
        return ruleNodes;
    }
}    